package org.java.auth.config;

import org.java.auth.handler.SmartHandler;
import org.java.auth.service.RemoteUserDetailsService;
import org.java.commons.vo.Result;
import org.java.user.api.PasswordEncoderConfig;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
import org.springframework.security.web.authentication.logout.HttpStatusReturningLogoutSuccessHandler;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Configuration
//导入加密配置
@Import(PasswordEncoderConfig.class)
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter implements WebMvcConfigurer {
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        super.configure(auth);
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        //css和它的子目录全部不需要权限(注册页面也不需要权限)
        web.ignoring()
                .mvcMatchers("/css/**","/js/**")
                .mvcMatchers("/images/**");
    }

    //  配置HTTP协议相关的安全选项，主要包括表单登录、登录结果
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                //permitAll表示允许任何权限的人访问，包括未登陆的
                .antMatchers("/login","/logout","user-info","do-login","/logout","/logout-success").permitAll()
                // 必须具有ADMIN这个身份的人才可以访问/admin/目录下的路径
                .antMatchers("/admin/**").hasRole("ADMIN")
                //任何请求
                .anyRequest()
                // 其他任何路径都必须授权以后才能访问，放到后面。
                .authenticated()

                .and()
                //使用表单登录
                .formLogin()
                // 修改默认的登录表单的用户名字段的名称
                .usernameParameter("loginName")
                .passwordParameter("password")
                //登录页面
                .loginPage("/login")
                //处理登录的URL
                .loginProcessingUrl("/do-login")
                //登录失败
                .failureHandler(new SmartHandler())
                //登录成功
                .successHandler(new SmartHandler())
                .and()
                //出现异常
                .exceptionHandling()
                //访问拒绝
                .accessDeniedHandler(new SmartHandler("/error"))
                // 还未登录时用于显示登录页面或者提示要登录。
                .authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/login") {
                    @Override
                    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException)
                            throws IOException, ServletException {
                        SmartHandler handler = new SmartHandler();
                        Result result = Result.error("还未登录");
                        response.setStatus(403);
                        if (!handler.sendJson(result, request, response)) {
                            super.commence(request, response, authException);
                        }
                    }
                })
                .and()
                //退出登录
                .logout()
                //处理退出登录的URL
                .logoutUrl("/logout")
                //处理登录成功
//                .logoutSuccessUrl("/logout-success")
                .logoutSuccessHandler(new HttpStatusReturningLogoutSuccessHandler())
//                .and()
//                //使用http Basic方式登录，在浏览器上面弹出对话框的方式，很少使用
//                .httpBasic()
                // 禁用CSRF攻击检测
                .and().csrf().disable();
        //配置跨源资源共享，需要有CorsConfigurationSource
        http.cors();
    }
    //显示页面
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/login")
                .setViewName("login");
    }
    @Bean//相当于《bean》元素
    @Override
    protected UserDetailsService userDetailsService() {
        return new RemoteUserDetailsService();
    }

    @Bean
    @Override
    public AuthenticationManager authenticationManager() throws Exception {
        return super.authenticationManager();
    }

}
